package xyz.wbsite.dbtool.javafx.manger.callable;

import xyz.wbsite.dbtool.javafx.manger.FreeMarkerManager;
import xyz.wbsite.dbtool.javafx.manger.ManagerFactory;
import xyz.wbsite.dbtool.javafx.po.Api;
import xyz.wbsite.dbtool.javafx.tool.EntityReader;
import xyz.wbsite.dbtool.javafx.tool.RequestReader;
import xyz.wbsite.dbtool.javafx.tool.ResponseReader;
import xyz.wbsite.dbtool.javafx.tool.Tool;
import xyz.wbsite.dbtool.javafx.tool.ResourceUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ApiCallable implements Callable {

    private File module;
    private File apiFile;
    private List<Api> apiList;
    private List<String> domainList;
    private Tool tool = new Tool();
    File apiDomain;
    File apiModule;
    File frame;
    File testApiDomain;
    private FreeMarkerManager freeMarkerManager;

    public ApiCallable(File module, File apiFile, List<String> domainList, List<Api> apiList) {
        this.module = module;
        this.apiFile = apiFile;
        this.apiList = apiList;
        this.domainList = domainList;
        this.freeMarkerManager = ManagerFactory.getFreeMarkerManager();
    }

    public Boolean call() throws Exception {
        if (!apiFile.exists()) {
            apiFile.mkdir();
        } else {
            Tool.clear(apiFile);
        }

        StringBuffer sbmain = new StringBuffer("");
        sbmain.append(this.apiFile.getPath() + File.separator);
        sbmain.append("src" + File.separator);
        sbmain.append("main" + File.separator);
        sbmain.append("java" + File.separator);

        StringBuffer sbtest = new StringBuffer("");
        sbtest.append(this.apiFile.getPath() + File.separator);
        sbtest.append("src" + File.separator);
        sbtest.append("test" + File.separator);
        sbtest.append("java" + File.separator);

        for (String s1 : domainList) {
            sbmain.append(s1 + File.separator);
            sbtest.append(s1 + File.separator);
        }

        apiDomain = Tool.createPath(sbmain.toString());
        apiModule = Tool.createPath(sbmain.toString(), "module");
        frame = Tool.createPath(sbmain.toString(), "frame");
        testApiDomain = Tool.createPath(sbtest.toString());

        for (Api api : apiList) {
            if (api.isCheck()) {
                RequestReader requestReader = new RequestReader(api.getRequestFile());
                api.setRequestFather(requestReader.getFatherName());
                generateRequest(requestReader);

                ResponseReader responseReader = new ResponseReader(api.getResponseFile());
                generateResponse(responseReader);
            }
        }

        {
            System.out.println("生成模块:Pom");
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("domain", String.join(".", domainList));
            ctx.put("name", apiFile.getName());
            freeMarkerManager.outputTemp(Tool.createFile(apiFile,"pom.xml"), "Java_api/pom.xml", ctx);
        }

        {
            File base = Tool.createPath(frame, "base");
            File client = Tool.createPath(frame, "client");
            File utils = Tool.createPath(frame, "utils");
            File okhttp3 = Tool.createPath(frame, "okhttp3");

            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("domain", String.join(".", domainList));
            for (String name : ResourceUtil.listFileName("/modules/Java_api/frame/base/")) {
                freeMarkerManager.outputTemp(Tool.createFile(base, name), "Java_api/frame/base/" + name, ctx);
            }

            for (String name : ResourceUtil.listFileName("/modules/Java_api/frame/client/")) {
                freeMarkerManager.outputTemp(Tool.createFile(client, name), "Java_api/frame/client/" + name, ctx);
            }

            for (String name : ResourceUtil.listFileName("/modules/Java_api/frame/utils/")) {
                if (name.equals("ValidationUtil.java")){//去掉验证 减少体积
                    continue;
                }
                freeMarkerManager.outputTemp(Tool.createFile(utils, name), "Java_api/frame/utils/" + name, ctx);
            }

            for (String name : ResourceUtil.listFileName("/modules/Java_api/frame/okhttp3/")) {
                freeMarkerManager.outputTemp(Tool.createFile(okhttp3, name), "Java_api/frame/okhttp3/" + name, ctx);
            }
        }

        generateTest();

        System.out.println("finish");
        return true;
    }

    private void generateTest() {
        Set<String> modules = new HashSet<>();
        for (Api api : apiList) {
            modules.add(api.getModule());
        }
        for (String m : modules) {

            ArrayList<Api> apis = new ArrayList<>();
            for (Api api : apiList) {
                if (m.equals(api.getModule())) {
                    apis.add(api);
                }
            }

            //生成Test
            System.out.println("生成模块:Test");
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("tool", tool);
            ctx.put("domain", String.join(".", domainList));

            HashSet<String> hashSet = new HashSet<>();
            for (Api api : apiList) {
                hashSet.add(api.getModule());
            }
            ctx.put("module", m);
            ctx.put("apiList", apis);
            ctx.put("className", Tool.abb2Abb(m) + "ApiTest");
            File api = Tool.createFile(testApiDomain.getAbsolutePath(), Tool.abb2Abb(m) + "ApiTest.java");
            freeMarkerManager.outputTemp(api, "Java_api/ApiTest.java", ctx);
        }
    }

    private void generateRequest(RequestReader reader) {
        String reqName = reader.getClassName();

        // 查找是否存在对应的Api,有则为公开的请求方法
        Api api = null;
        for (Api api1 : apiList) {
            if (api1.isCheck() && api1.getRequest().equals(reqName)) {
                api = api1;
            }
        }

        List<String> entNames = new ArrayList<>();
        for (String entName : reader.getDeptEntList()) {
            if (entName.matches("(.*\\.ent)\\.(.*)")) {
                Pattern compile = Pattern.compile("(.*\\.ent)\\.(.*)");
                Matcher matcher = compile.matcher(entName);

                if (matcher.find()) {
                    String EntName = matcher.group(2);
                    entNames.add(EntName);

                    List<File> files = Tool.findEntity(this.module, EntName + ".java");
                    for (File file : files) {
                        EntityReader entReader = new EntityReader(file);
                        generateEntity(entReader);
                    }
                }
            } else {
                List<File> files = Tool.findEntity(this.module, entName + ".java");
                for (File file : files) {
                    EntityReader entReader = new EntityReader(file);
                    generateEntity(entReader);
                }
            }

        }

        List<String> reqNames = new ArrayList<>();
        for (String depReqName : reader.getDeptReqList()) {
            if (depReqName.matches("(.*\\.req)\\.(.*)")) {
                Pattern compile = Pattern.compile("(.*\\.req)\\.(.*)");
                Matcher matcher = compile.matcher(depReqName);
                if (matcher.find()) {
                    entNames.add(depReqName);
                    List<File> files = Tool.findRequest(this.module, depReqName + ".java");
                    for (File file : files) {
                        RequestReader reqReader = new RequestReader(file);
                        generateRequest(reqReader);
                    }
                }
            } else {
                List<File> files = Tool.findRequest(this.module, depReqName + ".java");
                for (File file : files) {
                    generateRequest(new RequestReader(file));
                }
            }
        }

        {
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("domain", reader.getDomainName());
            ctx.put("module", reader.getModuleName());
            ctx.put("isTempReq", api == null);
            if (api != null) {
                ctx.put("target", api.getTarget());
                ctx.put("method", api.getMethod());
            } else {
                ctx.put("target", "");
                ctx.put("method", "");
            }
            ctx.put("importList", reader.getImportList());
            ctx.put("entNames", entNames);
            ctx.put("reqNames", reqNames);
            ctx.put("annotation", reader.getNotesList());
            ctx.put("className", reader.getClassName());
            ctx.put("fatherName", reader.getFatherName());
            ctx.put("rspClassName", reader.getClassName().replaceAll("Request", "Response"));
            ctx.put("body", reader.getBody());
            ctx.put("tool", tool);

            File req = Tool.createPath(apiModule.getAbsolutePath(), reader.getModuleName(), "req");
            File file = new File(req, reader.getClassName() + ".java");

            freeMarkerManager.outputTemp(file, "Java_api/module/req/request.java", ctx);
            System.out.println("生成文件" + file.getName() + "成功");
        }
    }

    private void generateResponse(ResponseReader reader) {
        List<String> entNames = new ArrayList<>();
        for (String s : reader.getDeptEntList()) {
            Pattern compile = Pattern.compile("(.*\\.ent)\\.(.*)");
            Matcher matcher = compile.matcher(s);

            if (matcher.find()) {
                String Package = matcher.group(1);
                String EntName = matcher.group(2);
                entNames.add(EntName);

                List<File> files = Tool.findEntity(this.module, EntName + ".java");

                for (File file : files) {
                    EntityReader entReader = new EntityReader(file);
                    generateEntity(entReader);
                }
            }
        }

        {
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("domain", reader.getDomainName());
            ctx.put("module", reader.getModuleName());
            ctx.put("importList", reader.getImportList());
            ctx.put("entNames", entNames);
            ctx.put("annotation", reader.getNotesList());
            ctx.put("className", reader.getClassName());
            ctx.put("body", reader.getBody());
            ctx.put("tool", tool);
            ctx.put("hasList", reader.isHasList());
            ctx.put("Tclass", reader.getTclass());

            File rsp = Tool.createPath(apiModule.getAbsolutePath(), reader.getModuleName(), "rsp");
            File file = new File(rsp, reader.getClassName() + ".java");

            freeMarkerManager.outputTemp(file, "Java_api/module/rsp/response.java", ctx);
            System.out.println("生成文件" + reader.getClassName() + "成功");
        }
    }

    private void generateEntity(EntityReader reader) {
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("domain", reader.getDomainName());
        ctx.put("module", reader.getModuleName());
        ctx.put("importList", reader.getImportList());
        ctx.put("annotation", reader.getNotesList());
        ctx.put("className", reader.getClassName());
        ctx.put("body", reader.getBody());
        ctx.put("tool", tool);
        File ent = Tool.createPath(apiModule.getAbsolutePath(), reader.getModuleName(), "ent");
        File EntFile = new File(ent, reader.getClassName() + ".java");
        freeMarkerManager.outputTemp(EntFile, "Java_api/module/ent/entity.java", ctx);
        System.out.println("生成文件" + reader.getClassName() + "成功");
    }
}
